const gui = new dat.GUI();
const PI = Math.PI;

// 每1秒，放大的倍率
var scaleSpeed = 1.1;

// 每1s时间，旋转1/8个圆
// 旋转秒速
var rotateSpeed_deg = 45;
var rotateSpeed_rad = rotateSpeed_deg * PI / 180;

// 弧度随t的变化
function getCORad(t) {
    return t * rotateSpeed_rad;
}

const params = {
    axisShow: true,

    scale: 1.1, // 放大比例

    // 曲线：起始半径、起始角度
    angleR0: 0.3,
    angle0: 0,

    // 参考曲线点：弧度点增量、绘制点数上限
    lineShow: true,
    lineAngleDelta: Math.PI / 4 / 100,
    linePointsLimit: 2121,

    // 圆：起始半径、开始的圆距0点距离、每个圆的间隔的点数
    circleR0: 6,
    drawCircleStartR: 34.3,
    drawCircleEveryN: 100,

    // rDelta: 0.001,    // 半径增量，单位：像素

    limit: 10000, // 绘制点数上限

    // angleDeltaDegrees: 1.8, // 弧度增量，单位：角度
    // angleDeltaSpeed: parseFloat((0.01 * Math.PI).toFixed(2)) // 弧度增量，单位：弧度，由angleDeltaDegrees自动维护
};

gui.add(params, 'axisShow').name('显示坐标系');
gui.add(params, 'scale', 0.1, 2).name('放大比例').step(0.01);

var group1 = gui.addFolder('圆弧参数');
group1.add(params, 'angleR0', 0.1, 1).name('起始半径').step(0.01);
group1.add(params, 'angle0', 0, Math.PI * 2).name('起始角度').step(0.01);
group1.add(params, 'lineShow').name('显示参考线');
group1.add(params, 'lineAngleDelta', 0.01, 0.1).step(0.001).name('参考线-角度增量');
group1.add(params, 'linePointsLimit', 1000, 5000).step(1).name('参考线-点数上限');

var group2 = gui.addFolder('圆点参数');
group2.add(params, 'circleR0', 2, 10).name('起始半径').step(0.1);
group2.add(params, 'drawCircleStartR', 30, 1000).name('开始绘制的范围半径').step(0.1);
group2.add(params, 'drawCircleEveryN', 10, 1000).name('每个圆的间隔的点数').step(1);


group1.open();
group2.open();


// 全局用的变量
var c = undefined;
var ctx = undefined;

// 方法定义 ========================================

// 设置画布宽高
function setCanvasSize() {
    var maxWH = Math.max(document.documentElement.clientWidth, document.documentElement.clientHeight);
    var minWH = Math.min(document.documentElement.clientWidth, document.documentElement.clientHeight);

    // 使用 document.documentElement.clientWidth 和 .clientHeight
    // c.width = maxWH;
    // c.height = maxWH;
    c.width = minWH;
    c.height = minWH;
    
    // 屏幕中心设为原点
    ctx.translate(c.width / 2, c.height / 2);
}

// 清空画布
function clearCanvas() {
    const ex = 10;
    // 清空画布
    ctx.clearRect(-c.width / 2 - ex, -c.height / 2 - ex, c.width + ex, c.height + ex);
}

// 绘制坐标轴
function drawAxis() {
    // 绘制原点（红色、7px、圆形、填充）
    ctx.fillStyle = "red";
    ctx.beginPath();
    ctx.arc(0, 0, 3, 0, Math.PI * 2);
    ctx.fill();
    ctx.closePath();
    

    ctx.beginPath();
    ctx.moveTo(-c.width / 2, 0);
    ctx.lineTo(c.width / 2, 0);
    ctx.moveTo(0, -c.height / 2);
    ctx.lineTo(0, c.height / 2);
    ctx.stroke();

    // 绘制坐标轴上的刻度
    for (var i = 0; i < c.width / 2; i += 20) {
        ctx.beginPath();
        ctx.moveTo(i, -5);
        ctx.lineTo(i, 5);
        ctx.stroke();
        
        ctx.beginPath();
        ctx.moveTo(-i, -5);
        ctx.lineTo(-i, 5);
        ctx.stroke();
    }
    for (var i = 0; i < c.height / 2; i += 20) {
        ctx.beginPath();
        ctx.moveTo(-5, i);
        ctx.lineTo(5, i);
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(-5, -i);
        ctx.lineTo(5, -i);
        ctx.stroke();
    }
    ctx.closePath();
}

// 判断当前x, y是否在画布内
function isInCanvas(x, y) {
    return x >= -c.width / 2 && x <= c.width / 2 && y >= -c.height / 2 && y <= c.height / 2;
}

// 绘制参考用的螺旋线
function drawLine() {
    // 绘制参考用的螺旋线
    var i = 0;
    var limit = params.linePointsLimit;
    var angle = params.angle0
    var angleR = params.angleR0;
    var drawPointsCount = 0;
    while(i < limit) {
        // 螺旋线点，当前角度
        angle = params.angle0 + i * params.lineAngleDelta;
        angleR = params.angleR0 * i * params.scale;
        var x = angleR * Math.cos(angle);
        var y = angleR * Math.sin(angle);
        ctx.beginPath();
        ctx.arc(x, y, 1, 0, Math.PI * 2);
        ctx.fill();
        ctx.closePath();

        drawPointsCount++;
        i++;
    }
}

// 绘制圆
function drawCircle() {
    // 绘制参考用的螺旋线
    var i = 0;
    var limit = params.linePointsLimit;
    var angle = params.angle0
    var angleR = params.angleR0;
    var drawPointsCount = 0;
    
    // 每一圈画n个圆
    var drawCircleStartR = params.drawCircleStartR;
    var drawCircleEveryN = params.drawCircleEveryN;

    var lastR = -1;

    while(i < limit) {
        // 螺旋线点，当前弧度
        angle = params.angle0 + i * params.lineAngleDelta;
        angleR = params.angleR0 * i * params.scale;
        
        var drawCircle = (angleR >= drawCircleStartR) && (i % drawCircleEveryN === 0);

        if (drawCircle) {
            var times = Math.floor(i / drawCircleEveryN);
            console.log("i * params.scale >>>", i * params.scale);
            console.log("times >>>", times);
            var currentCircleR = params.circleR0 * times * params.scale;
            var x = angleR * Math.cos(angle);
            var y = angleR * Math.sin(angle);

            console.log("放大倍率：", currentCircleR, lastR);
            lastR = currentCircleR;


            ctx.beginPath();
            ctx.arc(x, y, currentCircleR, 0, Math.PI * 2);
            ctx.fill();
            ctx.closePath();
        }

        drawPointsCount++;
        i++;
    }
}

// 绘制内容
function drawContent() {
    if (params.lineShow) {
        drawLine();
    }

    // 绘制圆点
    drawCircle();
}

// 每次绘制的方法
function draw() {
    clearCanvas();

    if (params.axisShow) {
        drawAxis();
    }
    
    drawContent();
    console.log("draw");
}

// 初始化，只运行依次的代码
function init() {
    c = document.body.querySelector("#c");
    ctx = c.getContext("2d");

    setCanvasSize();

    // 窗口大小调整时，重新设置宽高，并重新绘制
    window.onresize = function() {
        setCanvasSize();
        draw();
    }

    // 绘制一帧
    draw();
}

// 启动 ========================================

init();


var changeRedraw = function(controller) {
    controller.onChange(function() {
        draw();
    });
}
// GUI变量监听：当受控变量发生变化时，重新绘制
gui.__controllers.forEach(changeRedraw);
console.log("gui.__folders >>>", gui.__folders);
Array.from(Object.keys(gui.__folders)).forEach(function(folderName) {
    gui.__folders[folderName].__controllers.forEach(changeRedraw);
});


// 测试动画 =====================================
function startAnime() {
    // 先从canvas截图，放到页面上，然后一边以scale的倍率放大，一边旋转
    console.log("startAnime");

    // 每n个点的弧度
    var nAngle = params.drawCircleEveryN * params.lineAngleDelta;
    // 设定期望转n个点的弧度的时间
    var t = 1;
    // 弧度速度
    var radiansSpeed = nAngle / t;

    // 转换成角度速度
    var degreesSpeed = radiansSpeed * 180 / Math.PI;

    // 旋转一圈的秒数
    var turnARoundTime = 360 / degreesSpeed;

    // 旋转一圈，放大倍率
    var turnARoundScale = params.scale * turnARoundTime;

    console.log("旋转一圈秒数:", turnARoundTime);
    console.log("旋转一圈倍率:", turnARoundScale);

    // 获取canvas的DataURL
    var dataURL = c.toDataURL();
    var ctn = document.body.querySelector('.ctn');

    function imgGo() {
        console.log("imgGO!!!");
        // 创建一个新的Image对象
        var img = new Image();
        // 设置其来源为我们刚刚获取的DataURL
        img.src = dataURL;
        img.classList.add('canvas-img');
        img.style.transition = "";

        c.style.display = 'none';
        ctn.appendChild(img);

        // 应用动画
        img.style.setProperty('--turnARoundScale', turnARoundScale.toString());
        img.style.animation = `rotateAndScale ${turnARoundTime}s linear infinite`;
        img.style.opacity = "0.7";

        // if (x) {
        //     img.style.animation = `rotateAndScale1 ${turnARoundTime}s linear infinite`;
        // }
        // else {
        //     img.style.animation = `rotateAndScale ${turnARoundTime}s linear infinite`;
        // }

        // 旋转一周后，干掉自己
        setTimeout(function() {
            ctn.removeChild(img);
            
            console.log("img rm!!!");
        }, turnARoundTime * 1000);
    }

    // 每秒执行一次
    function repeatFunc() {
        imgGo();

        setTimeout(function() {
            repeatFunc();
        // }, turnARoundTime * 1000);
        }, 1000);
    }
    repeatFunc();

    // TODEL: 测试用代码
    // imgGo();
    // setTimeout(function(){
    //     imgGo(1);
    // }, 1000);

    ctn.style.transform = "translate(-50%, -50%)";
}

gui.add({
    startAnime
}, 'startAnime').name("开始动画")
